﻿using System;
using System.Collections.Generic;
using System.Security.Cryptography;

namespace Zo.Common
{
    /// <summary>
    /// 随机数管理器。
    /// </summary>
    public class RandomManager
    {
        private static readonly Random _random = new Random((int)DateTime.Now.Ticks);

        /// <summary>
        /// 区得 Random 对象。
        /// </summary>
        /// <returns></returns>
        public static Random GetRandom()
        {
            return _random;
        }

        #region 生成指定范围内的一个随机数

        private static readonly RNGCryptoServiceProvider _rngCryptoServiceProvider = new RNGCryptoServiceProvider();
        private static readonly byte[] _rngBytes = new byte[4];

        /// <summary>
        /// 产生一个非负数的乱数。
        /// </summary>
        /// <returns>随机数。</returns>
        public static int CreateRandomNumber()
        {
            _rngCryptoServiceProvider.GetBytes(_rngBytes);
            int value = BitConverter.ToInt32(_rngBytes, 0);
            if (value < 0) value = -value;
            return value;
        }

        /// <summary>
        /// 产生一个非负数且最大值在 max 以下的乱数。
        /// </summary>
        /// <param name="max">最大值。</param>
        /// <returns>随机数。</returns>
        public static int CreateRandomNumber(int max)
        {
            _rngCryptoServiceProvider.GetBytes(_rngBytes);
            int value = BitConverter.ToInt32(_rngBytes, 0);
            value = value % (max + 1);
            if (value < 0) value = -value;
            return value;
        }

        /// <summary>
        /// 产生一个非负数且最小值在 min 以上最大值在 max 以下的乱数。
        /// </summary>
        /// <param name="min">最小值（包含）。</param>
        /// <param name="max">最大值（不包含）。</param>
        /// <returns>随机数。</returns>
        public static int CreateRandomNumber(int min, int max)
        {
            if (min == max)
            {
                return max;
            }

            if (max < min)
            {
                return 0;
            }

            max--;

            int value = CreateRandomNumber(max - min) + min;

            return value;
        }

        ///// <summary>
        ///// 创建一个指定范围内的随机数字，并降低最小值出现的机率。
        ///// </summary>
        /// <param name="min">最小值（包含）。</param>
        /// <param name="max">最大值（不包含）。</param>
        /// <returns>随机数。</returns>
        public static int CreateRandomNumberLowMin(int min, int max)
        {
            if (min == max)
            {
                return max;
            }

            if (max < min)
            {
                return 0;
            }

            var container = new List<int>();

            for (var i = min; i <= max; i++)
            {
                if (i == min)
                {
                    container.Add(i);
                }
                else
                {
                    container.Add(i);
                    container.Add(i);
                }
            }

            var index = CreateRandomNumber(0, container.Count - 1);

            return container[index];
        }

        #endregion 生成指定范围内的一个随机数

        #region 生成指定范围内不重复的随机数组

        /// <summary>
        /// 生成指定范围内不重复的随机数。
        /// </summary>
        /// <param name="seed">随机数的种子。</param>
        /// <param name="Number">随机数个数</param>
        /// <param name="minNum">随机数下限</param>
        /// <param name="maxNum">随机数上限</param>
        /// <returns></returns>
        public static int[] GetRange(int seed, int Number, int minNum, int maxNum)
        {
            int j;
            int[] b = new int[Number];
            Random r = new Random(seed);
            for (j = 0; j < Number; j++)
            {
                int i = r.Next(minNum, maxNum + 1);
                int num = 0;
                for (int k = 0; k < j; k++)
                {
                    if (b[k] == i)
                    {
                        num = num + 1;
                    }
                }
                if (num == 0)
                {
                    b[j] = i;
                }
                else
                {
                    j = j - 1;
                }
            }
            return b;
        }

        #endregion 生成指定范围内不重复的随机数组
    }
}